﻿#include<iostream>
#include<cmath>

using namespace std;

//命题符号数组(6变量)
char proposition[] = {'P', 'Q', 'R', 'J', 'K', 'M'};
//真值结果数组(6变量)
char truthResult[64];

//存放该命题变项可能的取值(6变量)
int pResult[64];
int qResult[64];
int rResult[64];
int jResult[64];
int kResult[64];
int mResult[64];

//函数声明
void InitPropositionVariableValue(int num);
void OutputSingleValue(int value);
void OutputTruthTable(int num, char* truthResult, int len);
int CountMinterm(char* truthResult, int len);
int CountMaxterm(char* truthResult, int len);
void OutputSingleProposition(int value, int* result);
void OutputPrincipalDisjunctiveNormalForm(int num, char* truthResult, int len);
void OutputPrincipalConjunctiveNormalForm(int num, char* truthResult, int len);

int main() {

	/*目前最多支持三个命题变项*/
	
	//num用于表示命题变项的个数
	//len用于表示填入实际数据的truthResult的长度
	int num, len = 0;
	cout << "请输入变量个数: " << endl;
	cin >> num;

	cout << "请输入" << pow(2, num) << "个字符<用T 或 F表示>: " << endl;
	for (int i = 0; i < pow(2, num); i++) {
		cin >> truthResult[i];
		len++;
	}

	cout << "输出公式对应的真值表: " << endl;
	OutputTruthTable(num, truthResult, len);

	cout << "输出主析取范式: " << endl;
	OutputPrincipalDisjunctiveNormalForm(num, truthResult, len);
	cout << "\n输出主合取范式: " << endl;
	OutputPrincipalConjunctiveNormalForm(num, truthResult, len);
	cout << endl;

	system("pause");
}

/// <summary>
/// 初始化命题变项的取值
/// </summary>
/// <param name="num">命题变项的个数</param>
void InitPropositionVariableValue(int num) 
{
	//命题变项个数为1
	if (num == 1) 
	{
		//P赋值
		pResult[0] = 1;
		pResult[1] = 2;
	}
	//命题变项个数为2
	if (num == 2) 
	{
		//P赋值
		pResult[0] = 1;
		pResult[1] = 1;
		pResult[2] = 2;
		pResult[3] = 2;
		//Q赋值
		qResult[0] = 1;
		qResult[1] = 2;
		qResult[2] = 1;
		qResult[3] = 2;
	}
	//命题变项个数为3
	if (num == 3) 
	{
		//P赋值
		pResult[0] = 1;
		pResult[1] = 1;
		pResult[2] = 1;
		pResult[3] = 1;
		pResult[4] = 2;
		pResult[5] = 2;
		pResult[6] = 2;
		pResult[7] = 2;
		//Q赋值
		qResult[0] = 1;
		qResult[1] = 1;
		qResult[2] = 2;
		qResult[3] = 2;
		qResult[4] = 1;
		qResult[5] = 1;
		qResult[6] = 2;
		qResult[7] = 2;
		//R赋值
		rResult[0] = 1;
		rResult[1] = 2;
		rResult[2] = 1;
		rResult[3] = 2;
		rResult[4] = 1;
		rResult[5] = 2;
		rResult[6] = 1;
		rResult[7] = 2;
	}
}

//输出命题变项的取值(涉及由数字向字符的转换)
void OutputSingleValue(int value)
{
	//1代表T, 2代表F
	if (value == 1) {
		cout << "T\t";
	}
	if (value == 2) {
		cout << "F\t";
	}
}

/// <summary>
/// 输出真值表
/// </summary>
/// <param name="num">命题变项的个数</param>
/// <param name="trurhResult">存放真值结果的数组</param>
/// <param name="len">truthResult中存放真值结果的个数</param>
void OutputTruthTable(int num, char* truthResult, int len)
{
	//初始化命题变项的取值
	InitPropositionVariableValue(num);
	//输出命题变项
	for (int i = 0; i < num; i++) {
		cout << proposition[i] << "\t";
	}
	cout << 'A' << endl;
	
	//输出分割线(根据命题变项的个数动态调整)
	for (int i = 0; i < num; i++) {
		cout << "--------";
	}
	cout << "-" << endl;

	//输出真值表实际的每一行
	for (int i = 0; i < len; i++) //输出的行数
	{
		if (num == 1)		//命题变项个数为1 
		{
			OutputSingleValue(pResult[i]);
			cout << truthResult[i] << endl;
		}
		else if (num == 2)	//命题变项个数为2
		{
			OutputSingleValue(pResult[i]);
			OutputSingleValue(qResult[i]);
			cout << truthResult[i] << endl;
		}
		else if (num == 3)  //命题变项个数为3
		{
			OutputSingleValue(pResult[i]);
			OutputSingleValue(qResult[i]);
			OutputSingleValue(rResult[i]);
			cout << truthResult[i] << endl;
		}
	}
}

/// <summary>
/// 输出命题变项
/// </summary>
/// <param name="value">命题变项的真值</param>
/// <param name="result">存放命题变项真值结果的数组</param>
void OutputSingleProposition(int value, int* result)
{
	//处理P
	if (value == 1 && result == pResult)
	{
		cout << "P";
	}
	else if(value == 2 && result == pResult) 
	{
		cout << "非P";
	}
	//处理Q
	if (value == 1 && result == qResult)
	{
		cout << "Q";
	}
	else if (value == 2 && result == qResult)
	{
		cout << "非Q";
	}
	//处理R
	if (value == 1 && result == rResult)
	{
		cout << "R";
	}
	else if (value == 2 && result == rResult)
	{
		cout << "非R";
	}
}

//计数极小项
int CountMinterm(char* truthResult, int len) 
{
	int num = 0;
	for (int i = 0; i < len; i++) {
		if (truthResult[i] == 'T') {
			num++;
		}
	}

	return num;
}

//计数极大项
int CountMaxterm(char* truthResult, int len) {
	int num = 0;
	for (int i = 0; i < len; i++) {
		if (truthResult[i] == 'F') {
			num++;
		}
	}

	return num;
}

/// <summary>
/// 输出主析取范式
/// </summary>
/// <param name="num">命题变项的个数</param>
/// <param name="trurhResult">存放真值结果的数组</param>
/// <param name="len">truthResult中存放真值结果的个数</param>
void OutputPrincipalDisjunctiveNormalForm(int num, char* truthResult, int len)
{
	int j = 0;
	int minTerm = CountMinterm(truthResult, len);

	for (int i = 0; i < len; i++)
	{
		if (truthResult[i] == 'T')
		{
			if (num == 1) {
				OutputSingleProposition(pResult[i], pResult);
			}
			if (num == 2) {
				cout << "(";
				OutputSingleProposition(pResult[i], pResult);
				cout << "∧";
				OutputSingleProposition(qResult[i], qResult);
				cout << ")";
			}
			if (num == 3) {
				cout << "(";
				OutputSingleProposition(pResult[i], pResult);
				cout << "∧";
				OutputSingleProposition(qResult[i], qResult);
				cout << "∧";
				OutputSingleProposition(rResult[i], rResult);
				cout << ")";
			}
			//确保只在两最小项之间输出∨
			if (j < minTerm - 1) {
				cout << "∨";
			}
			j++;
		}
	}
}

/// <summary>
/// 输出主合取范式
/// </summary>
/// <param name="num">命题变项的个数</param>
/// <param name="trurhResult">存放真值结果的数组</param>
/// <param name="len">truthResult中存放真值结果的个数</param>
void OutputPrincipalConjunctiveNormalForm(int num, char* truthResult, int len)
{
	int j = 0;
	int maxTerm = CountMaxterm(truthResult, len);

	for (int i = 0; i < len; i++)
	{
		if (truthResult[i] == 'F')
		{
			if (num == 1) {
				OutputSingleProposition(pResult[i], pResult);
			}
			if (num == 2) {
				cout << "(";
				OutputSingleProposition(pResult[i], pResult);
				cout << "∨";
				OutputSingleProposition(qResult[i], qResult);
				cout << ")";
			}
			if (num == 3) {
				cout << "(";
				OutputSingleProposition(pResult[i], pResult);
				cout << "∨";
				OutputSingleProposition(qResult[i], qResult);
				cout << "∨";
				OutputSingleProposition(rResult[i], rResult);
				cout << ")";
			}
			//确保只在两最小项之间输出∨
			if (j < maxTerm - 1) {
				cout << "∧";
			}
			j++;
		}
	}
}
